import {IScene, ISceneItem} from 'obs-studio-node/module';
import {InputSourceModelType, InputSourceSettings, SceneModelType} from "@/types";

function isObject(value: any, type: string = 'object'): boolean {
    return typeof value === type && value !== null;
}

export function loopProperty(displayInput: any) {
    const obsProps = displayInput.properties;
    let obsProp = obsProps.first();
    let obj:any = {};
    do {
        console.log(obsProp.name, obsProp.details);
        obj[obsProp.name] = isObject(obsProp.details)
            ? JSON.parse(JSON.stringify(obsProp.details))
            : obsProp.details;
    } while ((obsProp = obsProp.next()));
    return obj;
}

export function transferSourceItem(item: ISceneItem): InputSourceModelType {
    return {
        id: item.source.id,
        locked: false,
        name: item.source.name,
        aliasName: item.source.name,
        scaleX: item.scale.x,
        scaleY: item.scale.y,
        sceneItemId: item.id,
        selected: false,
        settings: loopProperty(item.source),
        type: item.source.id,
        visible: item.visible,
        x: item.position.x,
        y: item.position.y,
        sort: item.id,
    } as InputSourceModelType;
}

export function transferScene(scene: IScene): SceneModelType {
    console.log('transferScene ', scene.name);
    let sourceList: InputSourceModelType[] = scene.getItems().map((item) => {
        return transferSourceItem(item);
    });
    return {
        items: sourceList,
        name: scene.name,
        selected: false,
        sort: 0,
    } as SceneModelType;
}

export class  SceneModelCollection {

    private static instance: SceneModelCollection

    public selectScene: SceneModelType
    public selectSource: InputSourceModelType | null
    private scenes: SceneModelType[] = [];

    private constructor() {
    }

    public static getInstance(): SceneModelCollection {
        if (!SceneModelCollection.instance) {
            SceneModelCollection.instance = new SceneModelCollection()
        }
        return SceneModelCollection.instance
    }

    get() {
        return this.scenes;
    }

    set(list: SceneModelType[]) {
        this.scenes = list
    }

    activeScene(sceneName: string) {
        let scene = this.scenes.find((x) => x.name === sceneName);
        this.selectScene = scene
        this.activeSource(null)
    }

    activeSource(sourceName: string | null) {
        if (sourceName === null) {
            if(this.selectSource){
                this.selectSource.selected =false
            }
            this.selectSource = null
            return
        }
        this.selectScene.items.forEach(item => {
            if (item.name === sourceName) {
                item.selected = true
                this.selectSource = item
            }
        })
    }

    getScene(name: string): SceneModelType | undefined {
        return this.scenes.find((x) => x.name === name);
    }

    addScene(scene: IScene): SceneModelType {
        let obj: SceneModelType;
        obj = transferScene(scene as IScene);
        const index = this.scenes.findIndex((x) => x.name === scene.name);
        if (index > -1) this.scenes.splice(index, 1, obj);
        else this.scenes.push(obj);
        this.initSort(this.scenes)
        this.activeScene(scene.name)
        this.activeSource(null)
        return obj;
    }

    removeScene(name: string): void {
        const index = this.scenes.findIndex((x) => x.name === name);
        const curSelected = this.scenes[index].name === name
        this.scenes.splice(index, 1);
        this.initSort(this.scenes)
        if (curSelected && this.scenes.length > 0) {
            this.activeScene(this.scenes[0].name)
        }
    }


    hasSourceName(name: string): boolean {
        const hasName = this.scenes.some((sceneItem) => {
            return sceneItem.items.some((sourceItem) => {
                return sourceItem.name === name;
            });
        });
        return hasName;
    }


    //source
    getSource(sceneName: string, name: string): InputSourceModelType | undefined {
        return this.selectScene.items.find((x) => x.name === name);
    }

    addSource(item: ISceneItem,aliasName?:string): InputSourceModelType {

        let source = transferSourceItem(item as ISceneItem)
        if(aliasName){
            source.aliasName = aliasName
        }
        this.selectScene.items.push(source);
        this.initSort(this.selectScene.items)
        this.activeSource(source.name)
        return source
    }

    removeSource(item: {name:string}) {

        let index;
        index = this.selectScene.items.findIndex(
            (x) => item.name === x.name,
        );
        console.log('remove index',index)
        this.selectScene.items.splice(index, 1);
        console.log('remove after',this.selectScene.items)
        this.initSort(this.selectScene.items)
        this.activeSource( null)
    }

    //重新排序
    initSort(list: any[]) {
        for (let i = 0; i < list; i++) {
            list[i].sort = i
        }
    }
//最下面 才是最顶点
    //改变位置
    exChangeScene(step: number) {
        const index = this.scenes.findIndex(scene => scene.name === this.selectScene.name)
        const stepIndex = index + step
        if (stepIndex > -1 && stepIndex < this.scenes.length) {
            const temp = this.scenes[index]
            this.scenes[index] = this.scenes[stepIndex]
            this.scenes[stepIndex] = temp
            this.initSort(this.scenes)
        }
    }

    //改变源位置
    exChangeSource(step: number) {
        const index = this.selectScene.items.findIndex(source => source.name === this.selectSource.name)
        const stepIndex = index + step
        if (stepIndex > -1 && stepIndex < this.selectScene.items.length) {
            const temp = this.selectScene.items[index]
            this.selectScene.items[index] = this.selectScene.items[stepIndex]
            this.selectScene.items[stepIndex] = temp
            this.initSort(this.selectScene.items)
        }
        this.selectSource = this.selectScene.items[stepIndex]

    }

    //设置对象属性
    settingProperty(obj: any, settings: InputSourceSettings) {
        if (obj === null) return
        for (let key in settings) {
            if (obj.hasOwnProperty(key)) {
                obj[key] = settings[key]
            }
        }
        return obj
    }

    toJSONString(): string {
        return JSON.stringify(this.scenes);
    }
}
